﻿--ref: http://kb.cnblogs.com/page/124787/
--1 - 执行计划
--执行计划是数据库根据sql语句和相关表的统计所做出的一个查询方案, 这个方案不是固定的, 会根据你的sql语句动态修改.
--需要注意: 
--* 1:写出来的sql语句对大小写要控制好,尽量重用查询计划, 保持同样查询的大小写一致, 如:
select * from tableA
SELECT * FROM tableA
--* 2:sql越简单越好, 越简单越容易被重复利用 
--* 3:查询语句尽量多用变量, 如:
 select * from tableA where begindate>'2012-5-1'
 select * from tableB where begindate>'2012-6-1'
 --所产生的执行计划是不同的, 但是如果使用
 select * from tableB where begindate>@input_date --其执行计划就可以重用了

--2 - 精简sql语句, 尽量避免写过长的语句(大于3层嵌套的执行计划会效率下降), 多用临时表, 好处很多, 可以在开始时对数据进行各种处理, 而不会影响到原数据, 同时减少对主表的扫描, 
--减少了共享锁的产生, 提高并发性

--3 - 绑定变量窥测
--* 概念: 倾斜字段 - 指的是某列中的绝大多数值都是相同的. 例如人口表里面民族一列, 基本上所有人都是汉族, 这样的字段就是倾斜字段.
--* 问题: 在倾斜字段中使用变量会产生问题, 因为绑定变量会重用执行计划, 如果第一次传入民族是"汉族", 则执行计划会选择全表扫描(执行计划会根据sql和表的信息进行制定). 
--  然后再次传入一个民族值是"布依族", 按理来说, 这个含有量很小很小, 应该使用索引查找, 但是由于重用了执行计划, 所以会再次进行全表扫描
--* 结论: 对倾斜字段不要使用绑定变量查找

--4 - 事务块越小越好
--begin tran和commit tran之间包含的块越小越好, 因为涉及的表越多并发性越差, 锁住的资源越多, 所以在保证数据一致性的前提下, 包含的块越小越好

--5 - nolock的使用
--使用with nolock 可以在一定程度上增加并发性, 因为读的时候不再申请共享锁, 但是注意如下情况慎用:
--* 1:查询的结果用于增删改操作的不能使用nolock ( 脏读 ?)
--* 2:查询的表属于频繁发生页分裂的:因为nolock读的时候不影响同时正在进行的修改, 所以如果表因为数据页满了引起分页, 则会产生跳读和重复读:
--  ** 跳读:要查的在第100页上, 还没读到但被分页到第99页, 则漏读了该记录产生跳读
--  ** 重复读:同上, 要查的在100页上, 读了之后分页, 排到101页, 再次读可能重复读
--* 3:能使用临时表提高并发的不要用nolock

--6 - 聚集索引没有建在表的顺序字段上，该表容易发生页分裂
--比如订单表，有订单编号orderid，也有客户编号customerid，那么聚集索引应该加在哪个字段上呢？对于该表，订单编号是顺序添加的，如果在orderid上加聚集索引，
--新增的行都是添加在末尾，这样不容易经常产生页分裂。
--然而，由于大多数查询都是根据客户编号来查的，因此，将聚集索引加在customerid上才有意义。而customerid对于订单表而言，并非顺序字段。
--比如“张三”的“customerid”是001，那么“张三”的订单信息必须都放在这张表的第一个数据页上，如果今天“张三”新下了一个订单，那该订单信息不能放在表的最后一页，而是第一页！如果第一页放满了呢？
--很抱歉，该表所有数据都要往后移动为这条记录腾地方。
--SQL Server的索引和Oracle的索引是不同的，SQL Server的聚集索引实际上是对表按照聚集索引字段的顺序进行了排序，相当于oracle的索引组织表。SQL Server的聚集索引就是表本身的一种组织形式，
--所以它的效率是非常高的。也正因为此，插入一条记录，它的位置不是随便放的，而是要按照顺序放在该放的数据页，如果那个数据页没有空间了，就引起了页分裂。所以很显然，聚集索引没有建在表的顺序字段上，
--该表容易发生页分裂。
--曾经碰到过一个情况，一位哥们的某张表重建索引后，插入的效率大幅下降了。估计情况大概是这样的。该表的聚集索引可能没有建在表的顺序字段上，该表经常被归档，所以该表的数据是以一种稀疏状态存在的。比如张三下过20张订单，而最近3个月的订单只有5张，归档策略是保留3个月数据，那么张三过去的15张订单已经被归档，留下15个空位，可以在insert发生时重新被利用。在这种情况下由于有空位可以利用，就不会发生页分裂。但是查询性能会比较低，因为查询时必须扫描那些没有数据的空位。
--重建聚集索引后情况改变了，因为重建聚集索引就是把表中的数据重新排列一遍，原来的空位没有了，而页的填充率又很高，插入数据经常要发生页分裂，所以性能大幅下降。
--对于聚集索引没有建在顺序字段上的表，是否要给与比较低的页填充率？是否要避免重建聚集索引？是一个值得考虑的问题！

--7 - 使用复合索引提高多个where条件的查询速度

--8 - 使用like进行模糊查询时应注意尽量不要使用前%
Select * from contact where username like '%ss%'
--由于ss前面用到了“%”，因此该查询必然走全表扫描，除非必要，否则不要在关键词前加%，

--9 - Row_number 会导致表扫描，用临时表分页更好, ROW_Number实现是基于order by的，排序对查询的影响显而易见
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--